package ncku.account.event;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;

import ncku.account.data.GlobalData;
import ncku.account.gui.categorySel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;

import com.toedter.calendar.JDateChooser;

/**
 * A simple demonstration application showing how to create a line chart using data from a
 * {@link CategoryDataset}.
 */
public class LineChart extends JPanel implements ActionListener {

    /**
     * Creates a new demo.
     *
     * @param title  the frame title.
     */
	private static JDateChooser startdate,enddate;
	private static JPanel bigP;
	private JPanel buttonP, checkP, chartP;
	private JButton btn1;
	private List<JCheckBox> checklist;
	
    public LineChart() {
    	chartP = new JPanel(); //initial
    	String[] cs = categorySel.getCategoriesList();
        checklist = new ArrayList<JCheckBox>(); // a list of checkboxes for categories
        checkP = new JPanel();
        checkP.setLayout(new GridLayout(cs.length, 1));
        for (int i=0; i<cs.length; i++) {
        	JCheckBox check = new JCheckBox(cs[i]); //new checkbox
        	check.addActionListener(actionListener);
        	checklist.add(check);
        	checkP.add(check);
        }
        checkP.setVisible(false);
    	setLayout(new BorderLayout()); //set layout
    	bigP = new JPanel(); //a big panel to include all other panel
		bigP.setLayout(new BorderLayout());
		btn1 = new JButton("Show"); //button to show chart
		btn1.addActionListener(this);
		startdate = new JDateChooser("yyyy/MM/dd","####/##/##",'_'); //date chooser
		enddate = new JDateChooser("yyyy/MM/dd","####/##/##",'_');
		buttonP = new JPanel();  //button panel with button and date chooser
		buttonP.setLayout(new FlowLayout());
		buttonP.add(new JLabel("Start"));
		buttonP.add(startdate);
		buttonP.add(new JLabel("End"));
		buttonP.add(enddate);
		buttonP.add(btn1);
		buttonP.setVisible(true);
		bigP.add(buttonP, BorderLayout.NORTH);
		bigP.add(checkP, BorderLayout.EAST);
		bigP.add(chartP, BorderLayout.CENTER);
		bigP.setVisible(true);
		add(bigP, BorderLayout.CENTER);
		setPreferredSize (new Dimension (681, 422));
		setVisible(true);
        
    }

    /**
     * Creates a sample dataset.
     * 
     * @return The dataset.
     */
    private CategoryDataset createDataset() {
	    String[] categories = new String [GlobalData.getTransactionNumber()+1];
	    String[] dates = new String[GlobalData.getTransactionNumber()];
	    DateFormat df = new SimpleDateFormat("yyyy/mm/dd");
	    int index,length = 0,check,dlength=0;
	    double temp;
	    for (int i = 0; i < GlobalData.getTransactionNumber(); i++){ //for each transaction
	    	check = -1;
	    	try { //check if inside the date requested
				if (df.parse(GlobalData.getTransaction(i).getDate()).before(startdate.getDate())) continue;
				if (df.parse(GlobalData.getTransaction(i).getDate()).after(enddate.getDate())) continue;
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			for (int j = 0; j < dlength; j++) { //check if the date included
				if (dates[j].equals(GlobalData.getTransaction(i).getDate())) {
					check = j;
					break;
				}
			}
			if (check == -1) { //if not included, include it
				dates[dlength] = GlobalData.getTransaction(i).getDate();
				dlength++;
			}
	    }
	    check = 0;
	    double[][] amount = new double [GlobalData.getTransactionNumber()+1][dlength];
	    for (int i = 0; i < GlobalData.getTransactionNumber(); i++){
	    	for (int j = 0; j < dlength; j++){
	    		amount[i][j] = 0;//initialize
	    	}
	    }
	    for (int i = 0; i < GlobalData.getTransactionNumber(); i++){
	    	try {//check date
				if (df.parse(GlobalData.getTransaction(i).getDate()).before(startdate.getDate())) continue;
				if (df.parse(GlobalData.getTransaction(i).getDate()).after(enddate.getDate())) continue;
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    	int checkbox = 0;
			for (int ci = 0; ci < checklist.size(); ci++) {
				if (checklist.get(ci).getText().equals(GlobalData.getTransaction(i).getCategory()) && checklist.get(ci).isSelected()) {
					checkbox = 1;
				}
			}
			if (checkbox == 0)
				continue;
			index = -1;
			for (int j = 0; j < length; j++) { //check if included in categories
				if (categories[j].equals(GlobalData.getTransaction(i).getCategory())) {
					index = j;
				}
			}
			for (int k = 0; k < dlength; k++){ //check if which the date belongs
				if (dates[k].equals(GlobalData.getTransaction(i).getDate())) {
					check = k;
					break;
				}
			}
			if (index == -1) { //if not included
				categories[length] = GlobalData.getTransaction(i).getCategory(); //new categories
				amount[length][check] = Double.parseDouble(GlobalData.getTransaction(i).getStringAmount()); //new amount
				length++;
				
			} else { //else
				temp = Double.parseDouble(GlobalData.getTransaction(i).getStringAmount()); //get amount
				amount[index][check] += temp; //add amount
			}

		}
	    categories[length] = "Balance"; // a balance categories
	    double balance = GlobalData.accountMoney; //initialize with initial money
	    double dayspend = 0;
	    for (int k=0; k < dlength; k++) {
	    	dayspend = 0;
	    	for (int g=0; g < length; g++) {
	    		dayspend += amount[g][k]; //get daily spend
	    	}
	    	balance -= dayspend; //find balance
	    	amount[length][k] = balance; //add to amount
	    }
	    length++;
	    
	    final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
	    
	    for (int i = 0; i < length; i++) {
	    	 for (int j = 0; j < dlength; j++) {
	    		 dataset.addValue(amount[i][j], categories[i], dates[j]); //set value into dataset
	    	 }
	    	
		}
        return dataset;
                
    }
    
    /**
     * Creates a sample chart.
     * 
     * @param dataset  a dataset.
     * 
     * @return The chart.
     */
    private JFreeChart createChart(final CategoryDataset dataset) {
        
        // create the chart...
        final JFreeChart chart = ChartFactory.createLineChart(
        	GlobalData.accountName,       // chart title
            "Date",                    // domain axis label
            "Amount",                   // range axis label
            dataset,                   // data
            PlotOrientation.VERTICAL,  // orientation
            true,                      // include legend
            true,                      // tooltips
            false                      // urls
        );

        chart.setBackgroundPaint(Color.white);

        final CategoryPlot plot = (CategoryPlot) chart.getPlot();
        plot.setBackgroundPaint(Color.lightGray);
        plot.setRangeGridlinePaint(Color.white);

        // customise the range axis...
        final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        rangeAxis.setAutoRangeIncludesZero(true);
        
        // customise the renderer...
        final LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
//        renderer.setDrawShapes(true);

        renderer.setSeriesStroke(
            0, new BasicStroke(
                2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
                1.0f, new float[] {10.0f, 6.0f}, 0.0f
            )
        );
        renderer.setSeriesStroke(
            1, new BasicStroke(
                2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
                1.0f, new float[] {6.0f, 6.0f}, 0.0f
            )
        );
        renderer.setSeriesStroke(
            2, new BasicStroke(
                2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
                1.0f, new float[] {2.0f, 6.0f}, 0.0f
            )
        );
        // OPTIONAL CUSTOMISATION COMPLETED.
        
        return chart;
    }
    
    /**
     * Starting point for the demonstration application.
     *
     * @param args  ignored.
     */
    public static void showline() {

        /*final LineChart demo = new LineChart(GlobalData.accountName);
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
        demo.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);*/
    }
    
    ActionListener actionListener = new ActionListener() { //action listener for checkbox, refresh chart when checkbox changed
    	public void actionPerformed(ActionEvent actionEvent) {
        	btn1.doClick(); //refresh
    	}
    };
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		bigP.remove(chartP);  //remove the chart panel
        
        final CategoryDataset dataset = createDataset();
        final JFreeChart chart = createChart(dataset);
        final ChartPanel chartPanel = new ChartPanel(chart);

        checkP.setVisible(true); //show check list
        chartP = new JPanel();
        chartP.add(chartPanel);  
		bigP.add(chartP, BorderLayout.CENTER);
		bigP.getRootPane().revalidate(); //refresh
	}

}

